package com.cw.jeeyt.service.impl.api;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.cw.jeeyt.common.enums.EnumYn;
import com.cw.jeeyt.common.utils.FileUtils;
import com.cw.jeeyt.dao.query.facade.FacadeClassQuery;
import com.cw.jeeyt.dao.query.facade.FacadeEnumQuery;
import com.cw.jeeyt.dao.query.facade.FacadeInfoQuery;
import com.cw.jeeyt.dao.query.facade.FacadeParamFieldQuery;
import com.cw.jeeyt.dao.query.facade.FacadeParamQuery;
import com.cw.jeeyt.service.converter.facade.FacadeParamConverter;
import com.cw.jeeyt.core.intf.facadeExcel.JavaDocReaderCore;
import com.cw.jeeyt.core.util.SessionUtil;
import com.cw.jeeyt.dao.intf.facade.FacadeClassDao;
import com.cw.jeeyt.dao.intf.facade.FacadeEnumDao;
import com.cw.jeeyt.dao.intf.facade.FacadeInfoDao;
import com.cw.jeeyt.dao.intf.facade.FacadeParamDao;
import com.cw.jeeyt.dao.intf.facade.FacadeParamFieldDao;
import com.cw.jeeyt.dao.intf.facade.FacadeProjectDao;
import com.cw.jeeyt.dao.model.facade.FacadeClassDo;
import com.cw.jeeyt.dao.model.facade.FacadeEnumDo;
import com.cw.jeeyt.dao.model.facade.FacadeInfoDo;
import com.cw.jeeyt.dao.model.facade.FacadeParamDo;
import com.cw.jeeyt.dao.model.facade.FacadeParamFieldDo;
import com.cw.jeeyt.dao.model.facade.FacadeProjectDo;
import com.cw.jeeyt.api.dto.facadeExcel.ApiCommonContent;
import com.cw.jeeyt.api.dto.facadeExcel.ApiEnum;
import com.cw.jeeyt.api.dto.facadeExcel.ApiEnumItem;
import com.cw.jeeyt.api.dto.facadeExcel.ApiFacade;
import com.cw.jeeyt.api.dto.facadeExcel.ApiGenerateFacadeExcelDto;
import com.cw.jeeyt.api.dto.facadeExcel.ApiMethod;
import com.cw.jeeyt.api.dto.facadeExcel.ApiParam;
import com.cw.jeeyt.api.dto.facadeExcel.ApiParamField;
import com.cw.jeeyt.api.enums.EnumFieldType;
import com.cw.jeeyt.api.enums.EnumParamType;
import com.cw.jeeyt.service.intf.api.ApiFacadeGenerateConfigService;
import com.cw.jeeyt.service.intf.api.ApiGenerateFacadeExcelService;
import com.cw.lang.common.utils.DateUtil;
import com.cw.lang.common.utils.GsonUtil;
import com.cw.lang.common.utils.IdGenerator;
import com.cw.lang.common.utils.SequenceTool;

/**
 * 生成接口文档工具类
 *
 * @author chenw
 */
@Service
public class ApiGenerateFacadeExcelServiceImpl implements ApiGenerateFacadeExcelService {

    private static final Logger logger = LoggerFactory.getLogger(ApiGenerateFacadeExcelServiceImpl.class);

    @Autowired
    private JavaDocReaderCore javaDocReaderCore;
    @Autowired
    private ApiFacadeGenerateConfigService generateConfigService;
    @Autowired
    private FacadeProjectDao facadeProjectDao;
    @Autowired
    private FacadeEnumDao facadeEnumDao;
    @Autowired
    private FacadeParamFieldDao facadeParamFieldDao;
    @Autowired
    private FacadeParamDao facadeParamDao;
    @Autowired
    private FacadeInfoDao facadeInfoDao;
    @Autowired
    private FacadeClassDao facadeClassDao;

    private static Integer currentRow = 0;
    private static Workbook workbook;

    private static CellStyle menuStyle;

    private static CellStyle cellStyle;

    private static CellStyle linkStyle;
    /**
     * 获取接口信息
     */
    private static List<ApiFacade> apiFacades;

    private List<FacadeEnumDo> insertFacadeEnumDos = new ArrayList<>();
    private List<FacadeEnumDo> updateFacadeEnumDos = new ArrayList<>();

    private static ApiCommonContent apiCommonContent;

    @Value("${facade.doc.generate.path}")
    private String facadeDocGeneratePath;
    @Value("${file.server.url}")
    private String fileServerUrl;

    /**
     * 生成接口文档方法
     */
    @Override
    public boolean generateFacadeExcel(ApiGenerateFacadeExcelDto facadeExcelDto) throws Exception {
        FileOutputStream xlsStream = null;
        try {
            insertFacadeEnumDos = new ArrayList<>();
            updateFacadeEnumDos = new ArrayList<>();
            //设置保存路径
            String docSavePath = "facadeDoc/" + DateUtil.date2String(new Date(), "yyyyMMdd");
            FileUtils.createDirectory(facadeDocGeneratePath + docSavePath);
            facadeExcelDto.setOutputPath(docSavePath + "/" + facadeExcelDto.getProjectName() + ".xlsx");
            //保存生成接口文档配置信息
            generateConfigService.saveGenerateConfig(facadeExcelDto);
            workbook = new XSSFWorkbook();
            menuStyle = formatMenu();
            cellStyle = formatCell();
            linkStyle = formatLinkCell();
            currentRow = 0;
            //模拟数据
            //mockData();
            //获取接口信息
            apiFacades = javaDocReaderCore.getFacadeInfo(facadeExcelDto);
            apiCommonContent = javaDocReaderCore.getCommonParams(facadeExcelDto);
            //2、存数据库
            saveFacadeInfo(facadeExcelDto, apiFacades);
            //3、生成excel
            exportExcel(facadeExcelDto);
            String outputPath = facadeExcelDto.getOutputPath();
            File xlsFile = new File(facadeDocGeneratePath + outputPath);
            if (!xlsFile.exists()) {
                FileUtils.createFile(outputPath);
            }
            //输出文件
            xlsStream = new FileOutputStream(xlsFile);
            workbook.write(xlsStream);
            logger.info("文档生成成功！,生成路径：{}", facadeDocGeneratePath + outputPath);
        } catch (Exception e) {
            logger.error("生成接口文档出错：{}", e.getMessage());
            e.printStackTrace();
            throw new Exception(e.getMessage());
        } finally {
            if (xlsStream != null) {
                xlsStream.close();
            }
        }
        return true;
    }

    /**
     * 保存接口信息到数据库
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveFacadeInfo(ApiGenerateFacadeExcelDto facadeExcelDto, List<ApiFacade> apiFacades) {
        //保存接口项目信息
        Long projectId = saveFacadeProject(facadeExcelDto);
        if (CollectionUtils.isNotEmpty(apiFacades)) {
            for (ApiFacade apiFacade : apiFacades) {
                //保存接口类信息
                Long classId = saveFacadeClass(projectId, apiFacade);
                //保存接口信息
                saveFacadeInfo(classId, apiFacade);
            }
            if(CollectionUtils.isNotEmpty(insertFacadeEnumDos)){
                logger.info("保存枚举信息：" + GsonUtil.objectToJsonString(insertFacadeEnumDos));
                facadeEnumDao.insertList(insertFacadeEnumDos);
            }
            if(CollectionUtils.isNotEmpty(updateFacadeEnumDos)){
                for (FacadeEnumDo facadeEnumDo : updateFacadeEnumDos) {
                    facadeEnumDao.updateBySelective(facadeEnumDo);
                }
            }
        }
    }

    /**
     * 保存接口项目信息
     */
    private Long saveFacadeProject(ApiGenerateFacadeExcelDto facadeExcelDto) {
        FacadeProjectDo checkProject = facadeProjectDao.selectByKey(facadeExcelDto.getId());
        FacadeProjectDo facadeProjectDo = new FacadeProjectDo();
        facadeProjectDo.setProjectCode(facadeExcelDto.getProjectCode());
        facadeProjectDo.setProjectName(facadeExcelDto.getProjectName());
        facadeProjectDo.setProjectComment(facadeExcelDto.getProjectName());
        facadeProjectDo.setCreateBy(SessionUtil.getSessionUserId());
        facadeProjectDo.setCreateDate(new Date());
        facadeProjectDo.setUpdateBy(SessionUtil.getSessionUserId());
        facadeProjectDo.setUpdateDate(new Date());
        facadeProjectDo.setDocPath(fileServerUrl + facadeExcelDto.getOutputPath());
        facadeProjectDo.setId(facadeExcelDto.getId());
        if (checkProject != null) {
            facadeProjectDao.updateBySelective(facadeProjectDo);
        } else {
            facadeProjectDao.insert(facadeProjectDo);
        }
        return facadeProjectDo.getId();
    }

    /**
     * 保存接口参数信息
     *
     * @param apiMethod
     */
    private Map<String, Object> saveFacadeParam(Long facadeInfoId, ApiMethod apiMethod) {
        Map<String, Object> paramMap = new HashMap<>();
        if (apiMethod == null) {
            return null;
        }
        List<FacadeParamDo> requestParamList = new ArrayList<>();
        List<FacadeParamDo> responseParamList = new ArrayList<>();
        List<FacadeParamDo> insertParams = new ArrayList<>();
        List<FacadeParamDo> updateParams = new ArrayList<>();
        List<FacadeParamFieldDo> insertFieldDos = new ArrayList<>();
        List<FacadeParamFieldDo> updateFieldDos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(apiMethod.getRequestParams())) {
            for (ApiParam apiParam : apiMethod.getRequestParams()) {
                FacadeParamDo paramDo = FacadeParamConverter.apiParam2Do(apiParam);
                Long paramId = SequenceTool.nextLongId();
                paramDo.setId(paramId);
                paramDo.setFacadeInfoId(facadeInfoId);
                FacadeParamDo existFacadeParam = checkFacadeParam(paramDo);
                if (existFacadeParam != null) {
                    paramDo.setId(existFacadeParam.getId());
                    updateParams.add(paramDo);
                } else {
                    insertParams.add(paramDo);
                }
                requestParamList.add(paramDo);
                if (StringUtils.isNotBlank(paramDo.getFields())) {
                    List<FacadeParamFieldDo> paramFieldDos = GsonUtil.jsonToList(paramDo.getFields(),
                        FacadeParamFieldDo.class);
                    for (FacadeParamFieldDo facadeParamFieldDo : paramFieldDos) {
                        facadeParamFieldDo.setParamId(paramDo.getId());
                        FacadeParamFieldDo checkDo = checkExistFacadeParamField(facadeParamFieldDo);
                        if (checkDo != null) {
                            facadeParamFieldDo.setId(checkDo.getId());
                            updateFieldDos.add(facadeParamFieldDo);
                        } else {
                            facadeParamFieldDo.setId(IdGenerator.nextId());
                            insertFieldDos.add(facadeParamFieldDo);
                        }
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(apiMethod.getFieldRequestParams())) {
            for (ApiParam apiParam : apiMethod.getFieldRequestParams()) {
                FacadeParamDo paramDo = FacadeParamConverter.apiParam2Do(apiParam);
                Long paramId = SequenceTool.nextLongId();
                paramDo.setId(paramId);
                paramDo.setFacadeInfoId(facadeInfoId);
                FacadeParamDo existFacadeParam = checkFacadeParam(paramDo);
                if (existFacadeParam != null) {
                    paramDo.setId(existFacadeParam.getId());
                    updateParams.add(paramDo);
                } else {
                    insertParams.add(paramDo);
                }
                requestParamList.add(paramDo);
                if (StringUtils.isNotBlank(paramDo.getFields())) {
                    List<FacadeParamFieldDo> paramFieldDos = GsonUtil.jsonToList(paramDo.getFields(),
                        FacadeParamFieldDo.class);
                    for (FacadeParamFieldDo facadeParamFieldDo : paramFieldDos) {
                        facadeParamFieldDo.setParamId(paramDo.getId());
                        FacadeParamFieldDo checkDo = checkExistFacadeParamField(facadeParamFieldDo);
                        if (checkDo != null) {
                            facadeParamFieldDo.setId(checkDo.getId());
                            updateFieldDos.add(facadeParamFieldDo);
                        } else {
                            facadeParamFieldDo.setId(IdGenerator.nextId());
                            insertFieldDos.add(facadeParamFieldDo);
                        }
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(apiMethod.getResponseParams())) {
            for (ApiParam apiParam : apiMethod.getResponseParams()) {
                FacadeParamDo paramDo = FacadeParamConverter.apiParam2Do(apiParam);
                Long paramId = SequenceTool.nextLongId();
                paramDo.setId(paramId);
                paramDo.setFacadeInfoId(facadeInfoId);
                FacadeParamDo existFacadeParam = checkFacadeParam(paramDo);
                if (existFacadeParam != null) {
                    paramDo.setId(existFacadeParam.getId());
                    updateParams.add(paramDo);
                } else {
                    insertParams.add(paramDo);
                }
                responseParamList.add(paramDo);
                if (StringUtils.isNotBlank(paramDo.getFields())) {
                    List<FacadeParamFieldDo> paramFieldDos = GsonUtil.jsonToList(paramDo.getFields(),
                        FacadeParamFieldDo.class);
                    for (FacadeParamFieldDo facadeParamFieldDo : paramFieldDos) {
                        facadeParamFieldDo.setParamId(paramDo.getId());
                        FacadeParamFieldDo checkDo = checkExistFacadeParamField(facadeParamFieldDo);
                        if (checkDo != null) {
                            facadeParamFieldDo.setId(checkDo.getId());
                            updateFieldDos.add(facadeParamFieldDo);
                        } else {
                            facadeParamFieldDo.setId(IdGenerator.nextId());
                            insertFieldDos.add(facadeParamFieldDo);
                        }
                    }
                }
            }
        }
        List<ApiParam> fieldResponseParams = apiMethod.getFieldResponseParams();
        if (CollectionUtils.isNotEmpty(fieldResponseParams)) {
            for (ApiParam apiParam : fieldResponseParams) {
                FacadeParamDo paramDo = FacadeParamConverter.apiParam2Do(apiParam);
                Long paramId = SequenceTool.nextLongId();
                paramDo.setId(paramId);
                paramDo.setFacadeInfoId(facadeInfoId);
                FacadeParamDo existFacadeParam = checkFacadeParam(paramDo);
                if (existFacadeParam != null) {
                    paramDo.setId(existFacadeParam.getId());
                    updateParams.add(paramDo);
                } else {
                    insertParams.add(paramDo);
                }
                responseParamList.add(paramDo);
                if (StringUtils.isNotBlank(paramDo.getFields())) {
                    List<FacadeParamFieldDo> paramFieldDos = GsonUtil.jsonToList(paramDo.getFields(),
                        FacadeParamFieldDo.class);
                    for (FacadeParamFieldDo facadeParamFieldDo : paramFieldDos) {
                        facadeParamFieldDo.setParamId(paramDo.getId());
                        FacadeParamFieldDo checkDo = checkExistFacadeParamField(facadeParamFieldDo);
                        if (checkDo != null) {
                            facadeParamFieldDo.setId(checkDo.getId());
                            updateFieldDos.add(facadeParamFieldDo);
                        } else {
                            facadeParamFieldDo.setId(IdGenerator.nextId());
                            insertFieldDos.add(facadeParamFieldDo);
                        }
                    }
                }
            }
        }
        if(CollectionUtils.isNotEmpty(insertFieldDos)){
            facadeParamFieldDao.insertList(insertFieldDos);
        }
        if(CollectionUtils.isNotEmpty(updateFieldDos)){
            for (FacadeParamFieldDo facadeParamFieldDo : updateFieldDos) {
                facadeParamFieldDao.updateBySelective(facadeParamFieldDo);
            }
        }
        if(CollectionUtils.isNotEmpty(insertParams)){
            facadeParamDao.insertList(insertParams);
        }
        if(CollectionUtils.isNotEmpty(updateParams)){
            for (FacadeParamDo facadeParamDo : updateParams) {
                facadeParamDao.updateBySelective(facadeParamDo);
            }
        }
        paramMap.put(EnumParamType.REQUEST.getCode(), requestParamList);
        paramMap.put(EnumParamType.RESPONSE.getCode(), responseParamList);
        return paramMap;
    }

    /**
     * 校验接口参数字段是否存在
     *
     * @param facadeParamFieldDo
     * @return
     */
    private FacadeParamFieldDo checkExistFacadeParamField(FacadeParamFieldDo facadeParamFieldDo) {
        Long paramId = facadeParamFieldDo.getParamId();
        String fieldCode = facadeParamFieldDo.getFieldCode();
        List<FacadeParamFieldDo> facadeParamFieldDos = facadeParamFieldDao.selectByExample(
            FacadeParamFieldQuery.builder()
                .paramId(paramId)
                .fieldCode(fieldCode)
                .build());
        return CollectionUtils.isNotEmpty(facadeParamFieldDos) ? facadeParamFieldDos.get(0) : null;
    }

    /**
     * 校验接口参数对象
     *
     * @param paramDo
     * @return
     */
    private FacadeParamDo checkFacadeParam(FacadeParamDo paramDo) {
        List<FacadeParamDo> facadeParamDos = facadeParamDao.selectByExample(FacadeParamQuery.builder()
            .paramCode(paramDo.getParamCode())
            .facadeInfoId(paramDo.getFacadeInfoId())
            .build());
        return CollectionUtils.isNotEmpty(facadeParamDos) ? facadeParamDos.get(0) : null;
    }

    /**
     * 保存接口枚举信息
     *
     * @param apiMethod
     */
    private List<Long> saveFacadeEnum(Long facadeInfoId, ApiMethod apiMethod) {
        if (CollectionUtils.isEmpty(apiMethod.getEnums())) {
            return null;
        }
        List<Long> enumIds = new ArrayList<>();
        for (ApiEnum apiEnum : apiMethod.getEnums()) {
            Long enumId = SequenceTool.nextLongId();
            FacadeEnumDo existsEnum = checkFacadeEnum(facadeInfoId, apiEnum);
            FacadeEnumDo facadeEnumDo = new FacadeEnumDo();
            if (existsEnum == null) {
                facadeEnumDo.setId(enumId);
            } else {
                enumId = existsEnum.getId();
            }
            facadeEnumDo.setFacadeId(facadeInfoId);
            facadeEnumDo.setEnumCode(apiEnum.getEnumCode());
            facadeEnumDo.setEnumName(apiEnum.getEnumDesc());
            facadeEnumDo.setEnumItems(GsonUtil.objectToJsonString(apiEnum.getItemList()));
            facadeEnumDo.setEnumComment(apiEnum.getEnumDesc());
            facadeEnumDo.setCreateBy(SessionUtil.getSessionUserId());
            facadeEnumDo.setUpdateBy(SessionUtil.getSessionUserId());
            facadeEnumDo.setCreateDate(new Date());
            facadeEnumDo.setUpdateDate(new Date());
            if (existsEnum == null) {
                insertFacadeEnumDos.add(facadeEnumDo);
            } else {
                updateFacadeEnumDos.add(facadeEnumDo);
            }
            enumIds.add(enumId);
        }
        return enumIds;
    }

    private FacadeEnumDo checkFacadeEnum(Long facadeInfoId, ApiEnum apiEnum) {
        List<FacadeEnumDo> enumDos = facadeEnumDao.selectByExample(FacadeEnumQuery.builder()
            .enumCode(apiEnum.getEnumCode())
            .facadeId(facadeInfoId)
            .build());
        if (CollectionUtils.isNotEmpty(enumDos)) {
            return enumDos.get(0);
        }
        return null;
    }

    /**
     * 保存接口信息
     *
     * @param apiFacade
     */
    private void saveFacadeInfo(Long classId, ApiFacade apiFacade) {
        List<FacadeInfoDo> facadeInfoDos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(apiFacade.getMethods())) {
            for (ApiMethod apiMethod : apiFacade.getMethods()) {
                Long facadeInfoId = SequenceTool.nextLongId();
                //通过classId+facadeCode判断是否已经存在，存在则更新
                List<FacadeInfoDo> checkList = facadeInfoDao.selectByExample(FacadeInfoQuery.builder()
                    .docId(classId)
                    .facadeCode(apiMethod.getMethodCode())
                    .build());
                if (CollectionUtils.isNotEmpty(checkList)) {
                    facadeInfoId = checkList.get(0)
                        .getId();
                }
                FacadeInfoDo facadeInfoDo = new FacadeInfoDo();
                facadeInfoDo.setDocId(classId);
                facadeInfoDo.setId(facadeInfoId);
                facadeInfoDo.setFacadeCode(apiMethod.getMethodCode());
                facadeInfoDo.setFacadeName(apiMethod.getMethodCode());
                if (StringUtils.isNotBlank(apiMethod.getMethodName())) {
                    facadeInfoDo.setFacadeName(apiMethod.getMethodName()
                        .length() > 500 ? apiMethod.getMethodName()
                        .substring(0, 400) : apiMethod.getMethodName());
                }
                facadeInfoDo.setFacadeRequestType(apiMethod.getAskType());
                facadeInfoDo.setFacadeUrl(apiMethod.getMethodUrl());
                //TODO 操作类型
                facadeInfoDo.setOperateType("query");
                facadeInfoDo.setFacadeVersion(apiFacade.getFacadeVersion());
                //保存接口枚举信息
                List<Long> enumIds = saveFacadeEnum(facadeInfoId, apiMethod);
                facadeInfoDo.setEnums(GsonUtil.objectToJsonString(enumIds));
                //保存接口参数信息
                Map<String, Object> paramMap = saveFacadeParam(facadeInfoId, apiMethod);
                facadeInfoDo.setRequests(GsonUtil.objectToJsonString(paramMap.get(EnumParamType.REQUEST.getCode())));
                facadeInfoDo.setResponses(GsonUtil.objectToJsonString(paramMap.get(EnumParamType.RESPONSE.getCode())));
                facadeInfoDo.setCreateBy(SessionUtil.getSessionUserId());
                facadeInfoDo.setUpdateBy(SessionUtil.getSessionUserId());
                facadeInfoDo.setCreateDate(new Date());
                facadeInfoDo.setUpdateDate(new Date());

                if (CollectionUtils.isNotEmpty(checkList)) {
                    facadeInfoDao.updateBySelective(facadeInfoDo);
                } else {
                    facadeInfoDos.add(facadeInfoDo);
                }
            } facadeInfoDao.insertList(facadeInfoDos);
        }
    }

    /**
     * 保存接口类信息
     *
     * @param apiFacade
     */
    private Long saveFacadeClass(Long projectId, ApiFacade apiFacade) {
        //通过projectId+classCode判断是否已经存在，存在则不新增，修改
        List<FacadeClassDo> facadeClassDos = facadeClassDao.selectByExample(FacadeClassQuery.builder()
            .classCode(apiFacade.getFacadeCode())
            .projectId(projectId)
            .build());
        FacadeClassDo facadeClassDo = new FacadeClassDo();
        Long id = IdGenerator.nextId();
        facadeClassDo.setId(id);
        //接口类编码
        facadeClassDo.setClassCode(apiFacade.getFacadeCode());
        //接口类名称
        facadeClassDo.setClassName(apiFacade.getFacadeName());
        //项目id
        facadeClassDo.setProjectId(projectId);
        //是否对外公开
        facadeClassDo.setIsPublic(EnumYn.Y.getCode());
        //接口说明
        facadeClassDo.setFacadeDesc(apiFacade.getFacadeName());
        facadeClassDo.setCreateBy(SessionUtil.getSessionUserId());
        facadeClassDo.setCreateDate(new Date());
        facadeClassDo.setUpdateBy(SessionUtil.getSessionUserId());
        facadeClassDo.setUpdateDate(new Date());
        if (CollectionUtils.isNotEmpty(facadeClassDos)) {
            facadeClassDo.setId(facadeClassDos.get(0)
                .getId());
            facadeClassDao.updateBySelective(facadeClassDo);
        } else {
            facadeClassDao.insertBySelective(facadeClassDo);
        }
        return facadeClassDo.getId();
    }

    /**
     * 导出excel
     */
    private void exportExcel(ApiGenerateFacadeExcelDto facadeExcelDto) throws Exception {
        //创建目录
        createCatalogSheet();
        //创建公共报文sheet
        createCommonParamSheet(facadeExcelDto);
        //创建接口sheet
        createDocSheet(facadeExcelDto);
    }

    /**
     * 创建公共报文sheet
     */
    private void createCommonParamSheet(ApiGenerateFacadeExcelDto facadeExcelDto) {
        Sheet sheet = workbook.createSheet("公共报文");
        sheet.setDisplayGridlines(false);
        //创建请求参数信息
        boolean first = true;
        createParamFieldRow(facadeExcelDto, sheet, apiCommonContent.getCommonRequestParams(),
            EnumParamType.COMMONREQUEST, EnumFieldType.CLASS, first);
        first = false;
        //创建响应参数信息
        createParamFieldRow(facadeExcelDto, sheet, apiCommonContent.getCommonResponseParams(),
            EnumParamType.COMMONRESPONSE, EnumFieldType.CLASS, first);
        //创建枚举信息
        createEnumRow(sheet, apiCommonContent.getApiEnumList(), first);
        //自适应宽度
        for (int i = 0; i < 5; i++) {
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, 5000);
            //sheet.setDefaultColumnStyle(i, cellStyle);
            //自适应宽度
            sheet.autoSizeColumn(i, true);
        }
    }

    /**
     * 创建目录
     */
    private static void createCatalogSheet() throws Exception {
        if (CollectionUtils.isEmpty(apiFacades)) {
            throw new Exception("数据为空");
        }
        Collections.sort(apiFacades, (o1, o2) -> {
            int res = o1.getFacadeNum()
                .compareTo(o2.getFacadeNum());
            return res;
        });

        Sheet catalogSheet = workbook.createSheet("目录");
        catalogSheet.setDisplayGridlines(false);
        Row catalogRow = catalogSheet.createRow(0);
        String[] menus = new String[] {"序号", "接口名", "接口描述","接口版本号", "请求方式", "请求路径", "方法描述"};
        for (int i = 0; i < menus.length; i++) {
            Cell cell = catalogRow.createCell(i);
            cell.setCellStyle(menuStyle);
            cell.setCellValue(menus[i]);
        }
        //创建目录列表
        int currentRow = 1;
        int i = 1;
        for (ApiFacade apiFacade : apiFacades) {
            //循环接口方法
            List<ApiMethod> apiMethods = apiFacade.getMethods();
            if (apiMethods == null || apiMethods.isEmpty()) {
                continue;
            }
            for (ApiMethod apiMethod : apiMethods) {
                Row tableRow = catalogSheet.createRow(currentRow);
                //序号
                Cell facadeNumCell = tableRow.createCell(0);
                //接口名
                Cell facadeCodeCell = tableRow.createCell(1);
                //接口描述
                Cell facadeDescCell = tableRow.createCell(2);
                //接口描述
                Cell facadeVersionCell = tableRow.createCell(3);
                //请求方式
                Cell askTypeCell = tableRow.createCell(4);
                //接口路径
                Cell methodCodeCell = tableRow.createCell(5);
                //方法描述
                Cell methodDescCell = tableRow.createCell(6);

                facadeNumCell.setCellValue(apiFacade.getFacadeNum());
                facadeCodeCell.setCellValue(apiFacade.getFacadeCode());
                facadeDescCell.setCellValue(apiFacade.getFacadeName());
                facadeVersionCell.setCellValue(apiFacade.getFacadeVersion());
                askTypeCell.setCellValue(apiMethod.getAskType());
                methodCodeCell.setCellValue(apiMethod.getMethodUrl());
                methodDescCell.setCellValue(apiMethod.getMethodName());
                facadeNumCell.setCellStyle(cellStyle);
                facadeCodeCell.setCellStyle(cellStyle);
                facadeDescCell.setCellStyle(cellStyle);
                facadeVersionCell.setCellStyle(cellStyle);
                askTypeCell.setCellStyle(cellStyle);
                methodCodeCell.setCellStyle(linkStyle);
                methodDescCell.setCellStyle(cellStyle);

                facadeCodeCell.setCellType(CellType.STRING);
                facadeDescCell.setCellType(CellType.STRING);
                facadeVersionCell.setCellType(CellType.STRING);
                askTypeCell.setCellType(CellType.STRING);
                methodCodeCell.setCellType(CellType.STRING);
                methodDescCell.setCellType(CellType.STRING);

                Hyperlink hyperlink = workbook.getCreationHelper()
                    .createHyperlink(HyperlinkType.DOCUMENT);
                String sheetName = i + "." + apiMethod.getMethodCode();
                if (sheetName.length() > 31) {
                    sheetName = sheetName.substring(0, 31);
                }
                hyperlink.setAddress("#" + sheetName + "!D1");
                methodCodeCell.setHyperlink(hyperlink);
                currentRow = currentRow + 1;
                i++;
            }
            if (CollectionUtils.isNotEmpty(apiMethods) && apiMethods.size() > 1) {
                catalogSheet.addMergedRegion(
                    new CellRangeAddress(currentRow - apiMethods.size(), currentRow - 1, 0, 0));
                catalogSheet.addMergedRegion(
                    new CellRangeAddress(currentRow - apiMethods.size(), currentRow - 1, 1, 1));
                catalogSheet.addMergedRegion(
                    new CellRangeAddress(currentRow - apiMethods.size(), currentRow - 1, 2, 2));
            }
        }
        //自适应宽度
        for (int j = 0; j < menus.length; j++) {
            catalogSheet.autoSizeColumn(j, true);
        }
    }

    /**
     * 创建接口sheet
     */
    private void createDocSheet(ApiGenerateFacadeExcelDto facadeExcelDto) {
        if (CollectionUtils.isEmpty(apiFacades)) {
            return;
        }
        //排序
        Collections.sort(apiFacades, (o1, o2) -> {
            int res = o1.getFacadeNum()
                .compareTo(o2.getFacadeNum());
            return res;
        });
        int ii = 1;
        for (ApiFacade apiFacade : apiFacades) {
            for (ApiMethod apiMethod : apiFacade.getMethods()) {
                logger.info("开始生成接口{}#{}文档信息", apiFacade.getFacadeCode(),apiMethod.getMethodCode());
                currentRow = 0;
                Sheet sheet = null;
                try {
                    String sheetName = ii + "." + apiMethod.getMethodCode();
                    if (sheetName.length() > 31) {
                        sheetName = sheetName.substring(0, 31);
                    }
                    sheet = workbook.createSheet(sheetName);
                    sheet.setDisplayGridlines(false);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //接口信息
                createFacadeSheetRow(facadeExcelDto, apiFacade, apiMethod, sheet, ii);
                //自适应宽度
                for (int i = 0; i < 5; i++) {
                    sheet.autoSizeColumn(i);
                    sheet.setColumnWidth(i, 5000);
                    //sheet.setDefaultColumnStyle(i, cellStyle);
                    //自适应宽度
                    sheet.autoSizeColumn(i, true);
                }
                ii++;
            }
        }
    }

    /**
     * 创建接口sheet信息
     *
     * @param apiFacade
     * @param apiMethod
     * @param sheet
     */
    private static void createFacadeSheetRow(ApiGenerateFacadeExcelDto facadeExcelDto, ApiFacade apiFacade,
        ApiMethod apiMethod, Sheet sheet, Integer sheetNum) {
        //公共请求参数
        List<ApiParam> commonRequestParams = new ArrayList<>();
        //请求参数
        List<ApiParam> requestParams = new ArrayList<>();
        //公共响应参数
        List<ApiParam> commonResponseParams = new ArrayList<>();
        //响应参数
        List<ApiParam> responseParams = new ArrayList<>();
        List<ApiParam> reqParams = apiMethod.getRequestParams();
        List<ApiParam> respParams = apiMethod.getResponseParams();
        //请求参数
        for (ApiParam apiParam : reqParams) {
            String paramType = apiParam.getParamType();
            if (EnumParamType.COMMONREQUEST.getCode()
                .equals(paramType)) {
                commonRequestParams.add(apiParam);
            } else if (EnumParamType.REQUEST.getCode()
                .equals(paramType)) {
                requestParams.add(apiParam);
            }
        }
        //响应参数
        for (ApiParam apiParam : respParams) {
            String paramType = apiParam.getParamType();
            if (EnumParamType.COMMONRESPONSE.getCode()
                .equals(paramType)) {
                commonResponseParams.add(apiParam);
            } else if (EnumParamType.RESPONSE.getCode()
                .equals(paramType)) {
                responseParams.add(apiParam);
            }
        }
        //菜单
        String[] menus = new String[] {"接口类名", "接口描述", "接口路径", "请求方式", "方法描述", "其他"};
        Row columnHeadRow = sheet.createRow(currentRow);
        for (int i = 0; i < menus.length; i++) {
            Cell cell = columnHeadRow.createCell(i);
            cell.setCellStyle(formatMenu());
            cell.setCellValue(menus[i]);
        }
        currentRow += 1;
        Row facadeRow = sheet.createRow(currentRow);
        for (int i = 0; i < menus.length; i++) {
            Cell cell = facadeRow.createCell(i);
            cell.setCellStyle(cellStyle);
            cell.setCellType(CellType.STRING);
            switch (i) {
                case 0:
                    cell.setCellValue(apiFacade.getFacadeCode());
                    break;
                case 1:
                    cell.setCellValue(apiFacade.getFacadeName());
                    break;
                case 2:
                    cell.setCellValue(apiMethod.getMethodUrl());
                    break;
                case 3:
                    cell.setCellValue(apiMethod.getAskType());
                    break;
                case 4:
                    cell.setCellValue(apiMethod.getMethodName());
                    break;
                case 5:
                    Hyperlink hyperlink = workbook.getCreationHelper()
                        .createHyperlink(HyperlinkType.DOCUMENT);
                    hyperlink.setAddress("#目录!D" + (sheetNum + 1));
                    cell.setCellStyle(linkStyle);
                    cell.setHyperlink(hyperlink);
                    cell.setCellValue("返回目录");
                    break;
            }
        }
        //创建公共请求参数信息
        createParamFieldRow(facadeExcelDto, sheet, commonRequestParams, EnumParamType.COMMONREQUEST,
            EnumFieldType.CLASS, false);
        //创建请求参数信息
        createParamFieldRow(facadeExcelDto, sheet, requestParams, EnumParamType.REQUEST, EnumFieldType.CLASS, false);
        //如果请求类的字段是对象，则也需要创建
        createParamFieldRow(facadeExcelDto, sheet, apiMethod.getFieldRequestParams(), EnumParamType.REQUEST,
            EnumFieldType.FIELD, false);
        //创建公共响应参数信息
        createParamFieldRow(facadeExcelDto, sheet, commonResponseParams, EnumParamType.COMMONRESPONSE,
            EnumFieldType.CLASS, false);
        //创建响应参数信息
        createParamFieldRow(facadeExcelDto, sheet, responseParams, EnumParamType.RESPONSE, EnumFieldType.CLASS, false);
        //如果响应类的字段是对象，则也需要创建
        createParamFieldRow(facadeExcelDto, sheet, apiMethod.getFieldResponseParams(), EnumParamType.RESPONSE,
            EnumFieldType.FIELD, false);
        //创建枚举信息
        createEnumRow(sheet, apiMethod.getEnums(), false);
    }

    /**
     * 创建枚举信息
     *
     * @param sheet
     */
    private static void createEnumRow(Sheet sheet, List<ApiEnum> enums, boolean first) {
        if (enums != null && !enums.isEmpty()) {
            if (!first) {
                currentRow += 1;
            }
            Row row = sheet.createRow(currentRow);
            sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow, 0, 5));
            String[] menus = null;
            Cell cell = row.createCell(0);
            cell.setCellStyle(formatMenu());
            cell.setCellValue("枚举信息");
            Cell cell1 = row.createCell(1);
            cell1.setCellStyle(formatMenu());
            cell1.setCellValue("");
            Cell cell2 = row.createCell(2);
            cell2.setCellStyle(formatMenu());
            cell2.setCellValue("");
            Cell cell3 = row.createCell(3);
            cell3.setCellStyle(formatMenu());
            cell3.setCellValue("");
            Cell cell4 = row.createCell(4);
            cell4.setCellStyle(formatMenu());
            cell4.setCellValue("");
            Cell cell5 = row.createCell(5);
            cell5.setCellStyle(formatMenu());
            cell5.setCellValue("");
            menus = new String[] {"枚举编码", "枚举名称", "code", "key", "desc", ""};
            currentRow += 1;
            Row columnMethodRow = sheet.createRow(currentRow);
            for (int i = 0; i < menus.length; i++) {
                cell = columnMethodRow.createCell(i);
                cell.setCellStyle(formatMenu());
                cell.setCellValue(menus[i]);
            }
            for (ApiEnum apiEnum : enums) {
                List<ApiEnumItem> items = apiEnum.getItemList();
                createEnumFieldRow(sheet, apiEnum, items, menus);
            }
        }
    }

    /**
     * 创建枚举详细信息
     *
     * @param sheet
     * @param apiEnum
     * @param items
     * @param menus
     */
    private static void createEnumFieldRow(Sheet sheet, ApiEnum apiEnum, List<ApiEnumItem> items, String[] menus) {
        if (items != null && !items.isEmpty()) {
            for (ApiEnumItem apiEnumItem : items) {
                currentRow += 1;
                Row row = sheet.createRow(currentRow);
                for (int i = 0; i < menus.length; i++) {
                    Cell cell = row.createCell(i);
                    cell.setCellStyle(cellStyle);
                    cell.setCellType(CellType.STRING);
                    switch (i) {
                        case 0:
                            cell.setCellValue(apiEnum.getEnumCode());
                            break;
                        case 1:
                            cell.setCellValue(apiEnum.getEnumDesc());
                            break;
                        case 2:
                            cell.setCellValue(apiEnumItem.getCode());
                            break;
                        case 3:
                            cell.setCellValue(apiEnumItem.getComment());
                            break;
                        case 4:
                            cell.setCellValue(apiEnumItem.getDesc());
                            break;
                    }
                }
            }
            if (CollectionUtils.isNotEmpty(items) && items.size() > 1) {
                sheet.addMergedRegion(new CellRangeAddress(currentRow - items.size() + 1, currentRow, 0, 0));
                sheet.addMergedRegion(new CellRangeAddress(currentRow - items.size() + 1, currentRow, 1, 1));
            }
        } else {
            logger.info("{}枚举找不到---------------------" + JSON.toJSONString(apiEnum), apiEnum.getEnumCode());
        }
    }

    /**
     * 创建参数对象信息
     *
     * @param sheet
     * @param fieldParam
     * @param fields
     * @param menus
     */
    private static void createFieldRow(Sheet sheet, ApiParam fieldParam, List<ApiParamField> fields, String[] menus) {
        if (fields != null && !fields.isEmpty()) {
            for (ApiParamField paramField : fields) {
                currentRow += 1;
                Row row = sheet.createRow(currentRow);
                for (int i = 0; i < menus.length; i++) {
                    Cell cell = row.createCell(i);
                    cell.setCellStyle(cellStyle);
                    cell.setCellType(CellType.STRING);
                    switch (i) {
                        case 0:
                            cell.setCellValue(fieldParam.getParamCode());
                            break;
                        case 1:
                            cell.setCellValue(paramField.getFieldCode());
                            break;
                        case 2:
                            cell.setCellValue(paramField.getFieldType());
                            break;
                        case 3:
                            cell.setCellValue(EnumYn.Y.getCode()
                                .equals(paramField.getIsRequired()) ? "是" : "否");
                            break;
                        case 4:
                            cell.setCellValue(paramField.getFieldName());
                            break;
                    }
                }
            }
            if (CollectionUtils.isNotEmpty(fields) && fields.size() > 1) {
                sheet.addMergedRegion(new CellRangeAddress(currentRow - fields.size() + 1, currentRow, 0, 0));
            }
        } else {
            logger.info("---------------------{}对象无参数或接口请求响应参数未实现Serializable接口，请排查", fieldParam.getParamCode());
            currentRow += 1;
            Row row = sheet.createRow(currentRow);
            for (int i = 0; i < menus.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(cellStyle);
                cell.setCellType(CellType.STRING);
                switch (i) {
                    case 0:
                        cell.setCellValue(fieldParam.getParamCode());
                        break;
                    case 1:
                        cell.setCellValue(fieldParam.getParamName());
                        break;
                    case 2:
                        cell.setCellValue(fieldParam.getParamCode());
                        break;
                    case 3:
                        cell.setCellValue("");
                        break;
                    case 4:
                        cell.setCellValue(fieldParam.getParamDesc());
                        break;
                }
            }
        }
    }

    /**
     * 创建参数信息
     *
     * @param sheet
     * @param params
     */
    private static void createParamFieldRow(ApiGenerateFacadeExcelDto facadeExcelDto, Sheet sheet,
        List<ApiParam> params, EnumParamType enumParamType, EnumFieldType fieldType, boolean first) {
        if (params != null && !params.isEmpty()) {
            if (!first) {
                currentRow += 1;
            }
            Row row = sheet.createRow(currentRow);
            sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow, 0, 5));
            String[] menus = null;
            Cell cell = row.createCell(0);
            cell.setCellStyle(formatMenu());
            if (enumParamType.getCode()
                .equals(EnumParamType.COMMONREQUEST.getCode())) {
                cell.setCellValue("Header信息");
                menus = new String[] {"请求类", "参数编码", "返回类型", "必输", "说明", ""};
            } else if (enumParamType.getCode()
                .equals(EnumParamType.REQUEST.getCode())) {
                cell.setCellValue("请求报文");
                if (EnumFieldType.FIELD == fieldType) {
                    cell.setCellValue("请求字段类");
                }
                menus = new String[] {"请求类", "参数编码", "返回类型", "必输", "说明", ""};
            } else if (enumParamType.getCode()
                .equals(EnumParamType.COMMONRESPONSE.getCode())) {
                cell.setCellValue("公共响应报文");
                menus = new String[] {"响应类", "参数编码", "返回类型", "必输", "说明", ""};
            } else if (enumParamType.getCode()
                .equals(EnumParamType.RESPONSE.getCode())) {
                cell.setCellValue("响应报文");
                if (EnumFieldType.FIELD == fieldType) {
                    cell.setCellValue("响应字段类");
                }
                menus = new String[] {"响应类", "参数编码", "返回类型", "必输", "说明", ""};
            }
            Cell cell1 = row.createCell(1);
            cell1.setCellStyle(formatMenu());
            cell1.setCellValue("");
            Cell cell2 = row.createCell(2);
            cell2.setCellStyle(formatMenu());
            cell2.setCellValue("");
            Cell cell3 = row.createCell(3);
            cell3.setCellStyle(formatMenu());
            cell3.setCellValue("");
            Cell cell4 = row.createCell(4);
            cell4.setCellStyle(formatMenu());
            cell4.setCellValue("");
            Cell cell5 = row.createCell(5);
            cell5.setCellStyle(formatMenu());
            cell5.setCellValue("");
            currentRow += 1;
            Row columnMethodRow = sheet.createRow(currentRow);
            for (int i = 0; i < menus.length; i++) {
                cell = columnMethodRow.createCell(i);
                cell.setCellStyle(formatMenu());
                cell.setCellValue(menus[i]);
            }
            //添加header请求参数：Content-Type
            String generateHeaderParam = facadeExcelDto.getGenerateHeaderParam();
            if (EnumYn.Y.getCode()
                .equals(generateHeaderParam) && enumParamType.getCode()
                .equals(EnumParamType.COMMONREQUEST.getCode())) {
                createHeaderRow(sheet, menus);
            }
            for (ApiParam apiParam : params) {
                List<ApiParamField> paramFields = apiParam.getFields();
                createFieldRow(sheet, apiParam, paramFields, menus);
            }
        }
    }

    /**
     * 添加header参数
     *
     * @param sheet
     * @param menus
     */
    private static void createHeaderRow(Sheet sheet, String[] menus) {
        List<ApiParamField> headParamFields = new ArrayList<>();
        ApiParamField contentTypeField = new ApiParamField();
        contentTypeField.setFieldCode("Content-Type");
        contentTypeField.setFieldName("数据类型");
        contentTypeField.setFieldType("String");
        contentTypeField.setIsRequired("是");
        contentTypeField.setRemark("application/json");
        headParamFields.add(contentTypeField);
        ApiParamField acceptTypeField = new ApiParamField();
        acceptTypeField.setFieldCode("Accept");
        acceptTypeField.setFieldName("接收参数");
        acceptTypeField.setFieldType("String");
        acceptTypeField.setIsRequired("是");
        acceptTypeField.setRemark("*/*");
        headParamFields.add(acceptTypeField);
        ApiParamField cacheTypeField = new ApiParamField();
        cacheTypeField.setFieldCode("Cache-Control");
        cacheTypeField.setFieldName("缓存控制");
        cacheTypeField.setFieldType("String");
        cacheTypeField.setIsRequired("是");
        cacheTypeField.setRemark("no-cache");
        headParamFields.add(cacheTypeField);
        for (ApiParamField apiParamField : headParamFields) {
            currentRow += 1;
            Row row = sheet.createRow(currentRow);
            for (int i = 0; i < menus.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(cellStyle);
                cell.setCellType(CellType.STRING);
                switch (i) {
                    case 0:
                        cell.setCellValue(apiParamField.getFieldCode());
                        break;
                    case 1:
                        cell.setCellValue(apiParamField.getFieldType());
                        break;
                    case 2:
                        cell.setCellValue(apiParamField.getRemark());
                        break;
                    case 3:
                        cell.setCellValue(apiParamField.getIsRequired());
                        break;
                    case 4:
                        cell.setCellValue(apiParamField.getFieldName());
                        break;
                }
            }
        }
    }

    /**
     * 格式化菜单
     *
     * @return HSSFCellStyle
     */
    private static CellStyle formatMenu() {
        //设置字体
        Font font = workbook.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 14);
        font.setBold(true);
        //粗体
        //font.setBold(true);

        CellStyle style = workbook.createCellStyle();
        style.setFont(font);
        //居中
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        //设置背景颜色
        style.setFillBackgroundColor(IndexedColors.SKY_BLUE.index);
        style.setFillForegroundColor(IndexedColors.SKY_BLUE.index);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        //设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        return style;
    }

    /**
     * 格式化菜单
     *
     * @return HSSFCellStyle
     */
    private static CellStyle formatTag() {
        //设置字体
        Font font = workbook.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 12);
        font.setBold(true);
        //粗体
        //font.setBold(true);

        CellStyle style = workbook.createCellStyle();
        style.setFont(font);
        //居中
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        //设置背景颜色
        style.setFillBackgroundColor((byte) 64);
        style.setFillForegroundColor((byte) 22);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        //设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        return style;
    }

    /**
     * 格式化单元格
     *
     * @return HSSFCellStyle
     */
    private static CellStyle formatCell() {

        //设置字体
        Font font = workbook.createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 10);
        font.setBold(false);

        CellStyle style = workbook.createCellStyle();

        style.setFont(font);

        //居中
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        //自动换行
        //style.setWrapText(true);
        return style;
    }

    /**
     * 链接
     *
     * @return
     */
    private static CellStyle formatLinkCell() {

        //设置字体
        Font font = workbook.createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 10);
        font.setBold(false);
        font.setColor(IndexedColors.BLUE.index);
        font.setUnderline((byte) 1);

        CellStyle style = workbook.createCellStyle();

        style.setFont(font);

        //居中
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        //设置边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        //自动换行
        //style.setWrapText(true);
        return style;
    }
}
